package com.panopset.gui;

import static com.panopset.Util.centerInScreen;
import static com.panopset.Util.x;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;

import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

import com.panopset.centralen.resource.Favicon;
import com.panopset.gui.container.PanCheckBox;

/**
 *
 * Typical Swing dialog box.
 *
 * @author Karl Dinwiddie
 *
 */
public final class TypicalDialog {

    /**
     * Title.
     */
    private final String title;

    /**
     * Frame.
     */
    private JDialog frame;

    /**
     * Remember password flag.
     */
    private boolean remember = false;

    /**
     * Dialog flavor.
     */
    public enum DIALOG_FLAVOR {
        /**
         * OK only dialog box.
         */
        OK_ONLY,

        /**
         * OK and Cancel buttons will be created.
         */
        OK_CANCEL
    }

    /**
     * Brings up a test dialog using the dspdlg method.
     *
     * @param s
     *            Not used.
     */
    public static void main(final String... s) {
        dspdlg("Test", "Message\nnext line.");
    }

    /**
     * Display a message in a dialog box.
     *
     * @param title
     *            Frame title
     * @param msg
     *            Message to appear in a non-editable ScrollPane in the dialog
     *            box.
     */
    public static void dspdlg(final String title, final String msg) {
        TPanel cp = new TPanel.Builder().layout(new GridLayout(1, 1))
                .construct();
        JTextArea ta = new JTextArea(msg);
        ta.setEditable(false);
        cp.add(new JScrollPane(ta));
        new TypicalDialog.Builder(title).centerPanel(cp).construct().getFrame()
                .setVisible(true);
    }

    /**
     * User cancelled flag.
     */
    private boolean userCancelled = false;

    /**
     * @return User cancelled flag.
     */
    public boolean isUserCancelled() {
        return userCancelled;
    }

    /**
     * Dialog width.
     */
    public static final int DIALOG_WIDTH = 600;

    /**
     * Dialog height.
     */
    public static final int DIALOG_HEIGHT = 300;

    /**
     * Dialog dimensions are 600, 300.
     */
    public static final Dimension DIALOG_DIMENSIONS = new Dimension(
            DIALOG_WIDTH, DIALOG_HEIGHT);

    /**
     * @param dialogTitle
     *            Title.
     */
    private TypicalDialog(final String dialogTitle) {
        title = dialogTitle;
    }

    /**
     * @return Dialog frame.
     */
    public JDialog getFrame() {
        if (frame == null) {
            frame = new JDialog();
            frame.setTitle(title);
            frame.setSize(DIALOG_DIMENSIONS);
            frame.setLocation(centerInScreen(DIALOG_DIMENSIONS));
            frame.setIconImage(Favicon.getLatest().getImageResource()
                    .getImage());
            frame.add(getPanel());
            frame.setModal(true);
            frame.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
            frame.getRootPane().setDefaultButton(getOkButton());
        }
        return frame;
    }

    /**
     * Exit.
     */
    protected void exit() {
        getFrame().dispose();
    }

    /**
     * Main panel.
     */
    private JPanel panel;

    /**
     * OK button.
     */
    private TButton okButton;

    /**
     * Cancel button.
     */
    private TButton cancelButton;

    /**
     * Remember password checkbox.
     */
    private PanCheckBox rememberCheckbox;

    /**
     * @return OK button.
     */
    public TButton getOkButton() {
        if (okButton == null) {
            okButton = new TButton();
            okButton.setText(x("OK"));
            okButton.setMnemonic(KeyEvent.VK_O);
            okButton.addActionListener(new ActionListener() {

                public void actionPerformed(final ActionEvent e) {
                    exit();
                }

            });
        }
        return okButton;
    }

    /**
     * @return Cancel button.
     */
    public TButton getCancelButton() {
        if (cancelButton == null) {
            cancelButton = new TButton();
            cancelButton.setText(x("Cancel"));
            cancelButton.setMnemonic(KeyEvent.VK_C);
            cancelButton.addActionListener(new ActionListener() {

                public void actionPerformed(final ActionEvent e) {
                    userCancelled = true;
                    exit();
                }

            });
        }
        return cancelButton;
    }

    /**
     * @return Remember password checkbox.
     */
    public PanCheckBox getRememberCheckbox() {
        if (rememberCheckbox == null) {
            rememberCheckbox = new PanCheckBox(x("Remember password"),
                    x("Make sure you only do this"
                            + " on your own private computer"
                            + ", as the password will be stored"
                            + " unencrypted on your disk."));
        }
        return rememberCheckbox;
    }

    /**
     * @return Main panel.
     */
    public JPanel getPanel() {
        if (panel == null) {
            panel = new JPanel();
        }
        return panel;
    }

    /**
     * Typical dialog builder.
     */
    public static final class Builder {
        /**
         * Title.
         */

        private String title;
        /**
         * North panel.
         */

        private JPanel northPnl;
        /**
         * Center panel.
         */

        private JPanel centerPnl;
        /**
         * Size.
         */

        private Dimension size;
        /**
         * Remember password flag.
         */
        private boolean remember = false;

        /**
         * Dialog flavor.
         */
        private DIALOG_FLAVOR flavor = DIALOG_FLAVOR.OK_ONLY;

        /**
         * @param dialogTitle
         *            Title.
         */
        public Builder(final String dialogTitle) {
            title = dialogTitle;
        }

        /**
         *
         * @param dialogFlavor
         *            default is OK_ONLY
         * @return Builder.
         */
        public Builder dialogFlavor(final DIALOG_FLAVOR dialogFlavor) {
            flavor = dialogFlavor;
            return this;
        }

        /**
         * Optional dialog size specification.
         *
         * @param dialogSize
         *            Defaults to w=600, h=300 if not specified here.
         * @return Builder.
         */
        public Builder size(final Dimension dialogSize) {
            size = dialogSize;
            return this;
        }

        /**
         *
         * @param northPanel North panel.
         * @return Builder.
         */
        public Builder northPanel(final JPanel northPanel) {
            northPnl = northPanel;
            return this;
        }

        /**
         *
         * @param centerPanel Center panel.
         * @return Builder.
         */
        public Builder centerPanel(final JPanel centerPanel) {
            this.centerPnl = centerPanel;
            return this;
        }

        /**
         * @return Typical dialog per Builder specifications.
         */
        public TypicalDialog construct() {
            TypicalDialog rtn = new TypicalDialog(title);
            rtn.remember = this.remember;
            rtn.getFrame().setLayout(new BorderLayout());
            if (northPnl != null) {
                rtn.getFrame().add(BorderLayout.CENTER, northPnl);
            }
            if (centerPnl != null) {
                rtn.getFrame().add(BorderLayout.CENTER, centerPnl);
            }
            if (size != null) {
                rtn.getFrame().setSize(size);
            }
            rtn.getFrame().add(BorderLayout.SOUTH,
                    rtn.assembleControlPanel(this.flavor));
            return rtn;
        }

        /**
         *
         * @return Builder.
         */
        public Builder remember() {
            remember = true;
            return this;
        }
    }

    /**
     * Assemble the control panel.
     *
     * @param dialogFlavor
     *            Dialog flavor.
     * @return Control panel.
     */
    private Component assembleControlPanel(final DIALOG_FLAVOR dialogFlavor) {
        TPanel controls = new TPanel.Builder().layout(new FlowLayout())
                .construct();
        switch (dialogFlavor) {
        case OK_CANCEL:
            controls.add(getCancelButton());
            controls.add(getOkButton());
            break;
        default:
            controls.add(getOkButton());
            break;
        }
        if (remember) {
            controls.add(getRememberCheckbox().getPanel());
        }
        return controls;
    }

    /**
     * Display the dialog.
     */
    public void display() {
        getFrame().setVisible(true);
    }
}
